package com.jumi.microservice.listener;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jumi.microservice.common.context.SpringApplicationContext;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.constant.ExceptionEnum;
import com.jumi.microservice.constant.GoodsKeyConstant;
import com.jumi.microservice.constant.GoodsStatus;
import com.jumi.microservice.constant.NumberConstant;
import com.jumi.microservice.domain.GoodsDO;
import com.jumi.microservice.domain.GoodsScheduleDO;
import com.jumi.microservice.domain.GoodsScheduleDTO;
import com.jumi.microservice.mapper.GoodsMapper;
import com.jumi.microservice.mapper.GoodsScheduleMapper;
import com.jumi.microservice.schedule.GoodsFixPuttedOnShelvesTask;
import com.jumi.microservice.service.GoodsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


/**
 * 系统初始化监听器
 *
 * @author Administrator
 */
@Component
public class SystemInitContextListener implements ApplicationListener<ApplicationStartedEvent> {

    private static final Logger logger = LoggerFactory.getLogger(SystemInitContextListener.class);

    @Autowired
    private SpringApplicationContext context;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private GoodsScheduleMapper goodsScheduleMapper;

    @Autowired
    private GoodsMapper goodsMapper;

    @Override
    public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
        if (!redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY)) {
            redisCache.setCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY, NumberConstant.NUMBER_ZERO.intValue());
        }

        GoodsService goodsService = context.getBean(GoodsService.class);
        List<GoodsScheduleDTO> scheduleGoods = goodsService.getScheduleGoods();
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(scheduleGoods.size());

        for (GoodsScheduleDTO goodsSchedule : scheduleGoods) {
            LocalDateTime date = goodsSchedule.getGoodsSelltime();

            exe.schedule(
                    () -> {
                        //调起任务
                        goodsSchedule.setIsSchedule(NumberConstant.NUMBER_ONE.intValue());
                        goodsSchedule.setUpdateTime(LocalDateTime.now());
                        GoodsScheduleDO goodsScheduleDO = convertGoodsScheduleDto2Do(goodsSchedule);
                        goodsScheduleMapper.updateById(goodsScheduleDO);

                        LambdaUpdateWrapper<GoodsDO> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.set(GoodsDO::getUpdateTime, LocalDateTime.now())
                                .set(GoodsDO::getGoodsState, GoodsStatus.PUTTED_ON_SHELVES.getCode())
                                .eq(GoodsDO::getId, goodsSchedule.getGoodsId());
                        int update = goodsMapper.update(new GoodsDO(), updateWrapper);

                        if (update > NumberConstant.NUMBER_ZERO.intValue()) {
                            if (redisCache.hasObjectByKey(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsSchedule.getGoodsId())) {
                                redisCache.deleteObject(GoodsKeyConstant.GOODS_DETAIL_KEY + goodsSchedule.getGoodsId());
                            }

                            goodsScheduleDO.setIsSuccess(NumberConstant.NUMBER_ONE.intValue());
                            goodsSchedule.setUpdateTime(LocalDateTime.now());
                            goodsScheduleMapper.updateById(goodsScheduleDO);
                        }
                    },
                    LocalDateTime.now().until(date, ChronoUnit.MILLIS),
                    TimeUnit.MILLISECONDS);
        }
        exe.shutdown();

        logger.info("【Commodity系统启动】系统已经完成启动!");
    }

    private GoodsScheduleDO convertGoodsScheduleDto2Do(GoodsScheduleDTO goodsScheduleDto) {
        GoodsScheduleDO goodsSchedule = null;
        try {
            goodsSchedule = goodsScheduleDto.clone(GoodsScheduleDO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return goodsSchedule;
    }
}